use std::time::Duration;

use bevy::{prelude::*, utils::HashMap};

use crate::{
    animate::{Animator, LoopStrategy},
    loader::GameSource,
    widget::{sprite, sprite_children, sprite_root, sprite_sheet},
    GameMaps,
};
use crate::collider::Colider;

const NOT_INIT: (usize, usize) = (99, 99);

///map center point
#[derive(Resource, Debug)]
pub struct GameMapSettings {
    pub show_line: bool,
    pub map_center: Vec2,
    pub physics_center: Vec2,
    pub map_cursor_pos: Vec2,
    pub map_cursor_block: (usize, usize),
    pub level_select: usize,
    pub block_select: [[usize; 2]; 2],
    pub map_size: (usize, usize),
    pub four_blocks: HashMap<usize, (usize, usize)>,
    pub moving_setting: Moving,
}

/// row col block_type
#[derive(Component, Debug)]
pub struct Block(pub usize, pub usize, pub usize);

#[derive(Component, Debug)]
pub struct FourBlock(pub usize, pub usize, pub usize);

impl Default for GameMapSettings {
    fn default() -> Self {
        Self {
            show_line: false,
            map_center: Vec2::default(),
            physics_center: Vec2::default(),
            map_cursor_pos: Vec2::default(),
            map_cursor_block: (0, 0),
            level_select: 0,
            block_select: [[0; 2]; 2],
            map_size: (26, 26),
            four_blocks: {
                let mut map = HashMap::default();
                map.insert(6, NOT_INIT);
                map.insert(7, NOT_INIT);
                map.insert(8, NOT_INIT);
                map
            },
            moving_setting: Moving::default(),
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum GameDirection {
    Up,
    Down,
    Left,
    Right,
}

#[derive(Component)]
pub struct Player {
    pub index: usize,
    pub moving_stack: Vec<GameDirection>,
}

impl Player {
    pub fn new_player1() -> Self {
        Self {
            index: 1,
            moving_stack: Vec::new(),
        }
    }

    pub fn new_player2() -> Self {
        Self {
            index: 2,
            moving_stack: Vec::new(),
        }
    }

    pub fn is_player1(&self) -> bool {
        self.index == 1
    }

    pub fn is_player2(&self) -> bool {
        self.index == 2
    }
}

#[derive(Component, Clone, Debug)]
pub struct Moving {
    pub speed: usize,
    pub direction: GameDirection,
    pub bullet_strength: usize,
}

impl Default for Moving {
    fn default() -> Self {
        Self {
            speed: 2,
            direction: GameDirection::Up,
            bullet_strength: 1,
        }
    }
}

#[derive(Component)]
pub struct Bullet {
    pub direction: usize,
    pub strength: usize,
}

#[derive(Component)]
pub struct MapPanelRelate;

///game map ui
pub fn ui_game_map(
    commands: Commands,
    mut game_map_settings: ResMut<GameMapSettings>,
    game_map: Res<GameMaps>,
) {
    sprite_root((), commands, (), |gc| {
        sprite_children(
            center_panel,
            gc,
            (Animator::default(), MapPanelRelate, Colider { width: 624., height: 624. }),
            |gc| {
                for (r, row) in game_map.maps[game_map_settings.level_select]
                    .map
                    .iter()
                    .enumerate()
                {
                    for (c, col) in row.iter().enumerate() {
                        if [1, 2, 5].contains(col) {
                            sprite(ui_block_class, gc, (Block(r, c, *col), Colider { width: 24., height: 24. }));
                        } else {
                            sprite(ui_block_class, gc, Block(r, c, *col));
                        }
                        if *col > 5 {
                            if let Some(val) = game_map_settings.four_blocks.get(col) {
                                if *val == NOT_INIT {
                                    game_map_settings.four_blocks.insert(*col, (r, c));
                                }
                            }
                        }
                    }
                }
                //出生点
                for (k, v) in game_map_settings.four_blocks.iter() {
                    match *k {
                        7 => sprite_sheet(
                            ui_four_block_class,
                            gc,
                            (FourBlock(v.0, v.1, *k), Player::new_player1(), game_map_settings.moving_setting.clone(), Colider { width: 48., height: 48. }),
                        ),
                        8 => sprite_sheet(
                            ui_four_block_class,
                            gc,
                            (FourBlock(v.0, v.1, *k), Player::new_player2(), game_map_settings.moving_setting.clone(), Colider { width: 48., height: 48. }),
                        ),
                        _ => sprite_sheet(ui_four_block_class, gc, FourBlock(v.0, v.1, *k)),
                    };
                }
            },
        );
    });
}

pub fn center_panel(
    mut sprite: Mut<Sprite>,
    mut transform: Mut<Transform>,
    mut image: Mut<Handle<Image>>,
    mut animator: Mut<Animator>,
    gm_res: Res<GameSource>,
    settings: Res<GameMapSettings>,
) {
    sprite.custom_size = Some(Vec2::new(630., 630.));
    transform.translation = Vec3::new(settings.map_center.x, settings.map_center.y + 100., 0.);
    *image = gm_res.world.clone();
    animator
        .set_loop_strategy(LoopStrategy::AllOnce)
        .add_change()
        .set_duration(Duration::from_millis(500));
    animator
        .add_change()
        .set_duration(Duration::from_secs(1))
        .set_transform_translation(Vec3::new(0., -100., 0.));
}

pub fn ui_four_block_class(
    mut image: Mut<Handle<Image>>,
    mut transform: Mut<Transform>,
    mut sprite: Mut<Sprite>,
    mut layout: Mut<TextureAtlas>,
    block: Mut<FourBlock>,
    gm_res: Res<GameSource>,
    settings: Res<GameMapSettings>,
) {
    if block.2 == 99 {
        sprite.color = Color::BLACK;
    } else {
        *image = gm_res.blocks[block.2 - 1].clone();
        sprite.color = Color::WHITE;
    }
    if block.2 == 6 {
        layout.layout = gm_res.tank_home.clone();
    } else {
        layout.layout = gm_res.tank_layout.clone();
    }
    sprite.custom_size = Some(Vec2::new(48., 48.));
    transform.translation.x = ((block.1 as i32) * 24 - 288) as f32 - settings.map_center.x;
    transform.translation.y = (288 - (block.0 as i32) * 24) as f32 - settings.map_center.y;
    transform.translation.z = 2.;
}

pub fn ui_block_class(
    mut image: Mut<Handle<Image>>,
    mut transform: Mut<Transform>,
    mut sprite: Mut<Sprite>,
    block: Mut<Block>,
    gm_res: Res<GameSource>,
    settings: Res<GameMapSettings>,
) {
    if block.2 < 6 && block.2 > 0 {
        *image = gm_res.blocks[block.2 - 1].clone();
        sprite.color = Color::WHITE;
    } else {
        sprite.color = Color::BLACK;
    }
    sprite.custom_size = Some(Vec2::new(24., 24.));
    transform.translation.x = ((block.1 as i32) * 24 - 300) as f32 - settings.map_center.x;
    transform.translation.y = (300 - (block.0 as i32) * 24) as f32 - settings.map_center.y;
    transform.translation.z = if block.2 == 4 { 4. } else { 1. };
}

pub fn ui_block_clear_class(
    mut image: Mut<Handle<Image>>,
    mut sprite: Mut<Sprite>,
    mut transform: Mut<Transform>,
) {
    sprite.color = Color::BLACK;
    *image = Handle::default();
    transform.translation.z = 0.;
}
